/*
 * commons is a based project implemented
 * Copyright (C) 2024 Jasmine
 */
package com.commons.core.executor;

import java.util.concurrent.*;

/**
 * Unified thread pool creation factory, and actively create thread pool resources by ThreadPoolManager for unified life
 * cycle management {@link ExecutorFactory}.
 *
 * <p>
 * Unified thread pool creation factory without life cycle management {@link ExecutorFactory}.
 *
 * <p>
 * two check style ignore will be removed after issue#2856 finished.
 */
@SuppressWarnings({"PMD.ThreadPoolCreationRule"})
public final class ExecutorFactory {

    private static final String DEFAULT_NAMESPACE = "project";

    private static final ThreadPoolManager THREAD_POOL_MANAGER = ThreadPoolManager.getInstance();

    /**
     * Create a new single executor service with default thread factory and register to manager.
     *
     * @param group group name
     * @return new single executor service
     */
    public static ExecutorService newSingleExecutorService(final String group) {
        ExecutorService executorService = Executors.newFixedThreadPool(1);
        THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
        return executorService;
    }

    /**
     * Create a new single executor service with input thread factory and register to manager.
     *
     * @param group group name
     * @param threadFactory thread factory
     * @return new single executor service
     */
    public static ExecutorService newSingleExecutorService(final String group, final ThreadFactory threadFactory) {
        ExecutorService executorService = Executors.newFixedThreadPool(1, threadFactory);
        THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
        return executorService;
    }

    /**
     * Create a new fixed executor service with default thread factory and register to manager.
     *
     * @param group group name
     * @param nThreads thread number
     * @return new fixed executor service
     */
    public static ExecutorService newFixedExecutorService(final String group, final int nThreads) {
        ExecutorService executorService = Executors.newFixedThreadPool(nThreads);
        THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
        return executorService;
    }

    /**
     * Create a new fixed executor service with input thread factory and register to manager.
     *
     * @param group group name
     * @param nThreads thread number
     * @param threadFactory thread factory
     * @return new fixed executor service
     */
    public static ExecutorService newFixedExecutorService(final String group, final int nThreads,
        final ThreadFactory threadFactory) {
        ExecutorService executorService = Executors.newFixedThreadPool(nThreads, threadFactory);
        THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
        return executorService;
    }

    /**
     * Create a new single scheduled executor service with input thread factory and register to manager.
     *
     * @param group group name
     * @param threadFactory thread factory
     * @return new single scheduled executor service
     */
    public static ScheduledExecutorService newSingleScheduledExecutorService(final String group,
        final ThreadFactory threadFactory) {
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1, threadFactory);
        THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
        return executorService;
    }

    /**
     * Create a new scheduled executor service with input thread factory and register to manager.
     *
     * @param group group name
     * @param nThreads thread number
     * @param threadFactory thread factory
     * @return new scheduled executor service
     */
    public static ScheduledExecutorService newScheduledExecutorService(final String group, final int nThreads,
        final ThreadFactory threadFactory) {
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(nThreads, threadFactory);
        THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
        return executorService;
    }

    /**
     * Create a new custom executor service and register to manager.
     *
     * @param group group name
     * @param coreThreads core thread number
     * @param maxThreads max thread number
     * @param keepAliveTimeMs keep alive time milliseconds
     * @param threadFactory thread factory
     * @return new custom executor service
     */
    public static ThreadPoolExecutor newCustomerThreadExecutor(final String group, final int coreThreads,
        final int maxThreads, final long keepAliveTimeMs, final ThreadFactory threadFactory) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(coreThreads, maxThreads, keepAliveTimeMs,
            TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), threadFactory);
        THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executor);
        return executor;
    }
}
